package impl

import (
	"context"

	"gitee.com/go-course/go11/vblog/apps/blog"
	"gitee.com/go-course/go11/vblog/conf"
	"gitee.com/go-course/go11/vblog/ioc"
	"gorm.io/gorm"
)

// 现在这个业务实现的包, 封装完整, 并且不对外开发, 只能通过ioc访问
// 保证了业务实现的安全
// 这个对象满足2从身份: 业务服务/Ioc Controller托管

// 声明一个变了_, 为啥声明的一个变量又不用他的指，只想要他的接口约束
var _ blog.Service = &impl{
	// 能不能这样写, 答案是不能
	// 包被调用，这些变量就得里面赋值
	// 你调用的时候，config还没有初始化, C的值为空
	// c: conf.C(),
}

// 先定义一个对象, 由这个对象来实现业务功能
// impl 才实现了业务接口生成
// 现在 impl对象 充当的是 mvc里面的控制器
// 控制器实现了一个核心业务方法:  CreateBlog
// 依赖myql的配置, 怎么访问MySQL
type impl struct {
	db *gorm.DB
}

// 业务实例如何访问配置
// 通常为这个实例类 提供初始化方法
// 在配置初始化好后, 再调用
func (i *impl) Init() error {
	// 每个业务模块, 都建立一个mysql连接池 比较浪费
	// 比如这种配置上的全局共享对象, 直接通过为这个配置封装方法来进行互用
	db := conf.C().MySQL.ORM()
	//
	i.db = db.Debug()
	return nil
}

func (i *impl) GetDB(ctx context.Context) *gorm.DB {
	return i.db.WithContext(ctx).Model(&blog.Blog{})
}

// 对象的名称, 用于去获取对象, 通常把这个名称定制一个模块常量
func (i *impl) Name() string {
	return blog.AppName
}

// 怎么把这个对象托管到Ioc
// 通过Import的方式，自动调用包的init方法，把需要托管的对象注册到ioc中
// import _ "gitee.com/go-course/go11/vblog/apps/blog/impl"
func init() {
	ioc.RegistryController(&impl{})
}
